package com.hjh.gameforum.service;

import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.SortOrder;
import co.elastic.clients.elasticsearch.core.SearchResponse;
import co.elastic.clients.elasticsearch.core.search.Hit;
import co.elastic.clients.json.JsonData;
import com.hjh.gameforum.entity.Topic;
import com.hjh.gameforum.enums.TopicStatus;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 话题搜索服务
 */
@Service
public class TopicSearchService extends BaseElasticsearchService {

    private static final String TOPIC_INDEX = "topics";

    public TopicSearchService(ElasticsearchClient elasticsearchClient) {
        super(elasticsearchClient);
    }

    /**
     * 1. 全文本搜索（标题和内容）
     */
    public List<Topic> searchTopics(String keyword) throws IOException {
        SearchResponse<Topic> response = getClient().search(s -> s
                        .index(TOPIC_INDEX)
                        .query(q -> q
                                .multiMatch(m -> m
                                        .query(keyword)
                                        .fields("title^3", "content^2") // 标题权重更高
                                        .fuzziness("AUTO") // 模糊搜索，容错拼写错误
                                )
                        )
                        .sort(so -> so.field(f -> f.field("createdAt").order(SortOrder.Desc))) // 按创建时间倒序
                        .from(0)
                        .size(50),
                Topic.class
        );

        return extractResults(response);
    }

    /**
     * 2. 按分类搜索
     */
    public List<Topic> searchTopicsByCategory(String keyword, Long categoryId) throws IOException {
        SearchResponse<Topic> response = getClient().search(s -> s
                        .index(TOPIC_INDEX)
                        .query(q -> q
                                .bool(b -> {
                                    // 关键词搜索
                                    if (keyword != null && !keyword.trim().isEmpty()) {
                                        b.must(m -> m
                                                .multiMatch(multi -> multi
                                                        .query(keyword)
                                                        .fields("title", "content")
                                                )
                                        );
                                    }

                                    // 分类过滤
                                    b.filter(f -> f
                                            .term(t -> t
                                                    .field("categoryId")
                                                    .value(categoryId)
                                            )
                                    );

                                    // 只搜索已发布的话题
                                    b.filter(f -> f
                                            .term(t -> t
                                                    .field("status")
                                                    .value(TopicStatus.open.name())
                                            )
                                    );

                                    return b;
                                })
                        )
                        .sort(so -> so.field(f -> f.field("createdAt").order(SortOrder.Desc)))
                        .from(0)
                        .size(50),
                Topic.class
        );

        return extractResults(response);
    }

    /**
     * 3. 热门话题搜索（按浏览量排序）
     */
    public List<Topic> searchPopularTopics(String keyword) throws IOException {
        SearchResponse<Topic> response = getClient().search(s -> s
                        .index(TOPIC_INDEX)
                        .query(q -> q
                                .bool(b -> {
                                    if (keyword != null && !keyword.trim().isEmpty()) {
                                        b.must(m -> m
                                                .multiMatch(multi -> multi
                                                        .query(keyword)
                                                        .fields("title", "content")
                                                )
                                        );
                                    }

                                    // 只搜索已发布的话题
                                    b.filter(f -> f
                                            .term(t -> t
                                                    .field("status")
                                                    .value(TopicStatus.open.name())
                                            )
                                    );

                                    return b;
                                })
                        )
                        .sort(so -> so.field(f -> f.field("viewCount").order(SortOrder.Desc))) // 按浏览量倒序
                        .sort(so -> so.field(f -> f.field("createdAt").order(SortOrder.Desc)))
                        .from(0)
                        .size(20),
                Topic.class
        );

        return extractResults(response);
    }

    /**
     * 4. 按时间范围搜索
     */
    public List<Topic> searchTopicsByDateRange(String keyword, LocalDateTime startDate, LocalDateTime endDate) throws IOException {
        SearchResponse<Topic> response = getClient().search(s -> s
                        .index(TOPIC_INDEX)
                        .query(q -> q
                                .bool(b -> {
                                    if (keyword != null && !keyword.trim().isEmpty()) {
                                        b.must(m -> m
                                                .multiMatch(multi -> multi
                                                        .query(keyword)
                                                        .fields("title", "content")
                                                )
                                        );
                                    }

                                    // 时间范围过滤
                                    b.filter(f -> f
                                            .range(r -> r
                                                    .field("createdAt")
                                                    .gte(JsonData.fromJson(startDate.toString()))
                                                    .lte(JsonData.fromJson(endDate.toString()))
                                            )
                                    );

                                    // 只搜索已发布的话题
                                    b.filter(f -> f
                                            .term(t -> t
                                                    .field("status")
                                                    .value(TopicStatus.open.name())
                                            )
                                    );

                                    return b;
                                })
                        )
                        .sort(so -> so.field(f -> f.field("createdAt").order(SortOrder.Desc)))
                        .from(0)
                        .size(50),
                Topic.class
        );

        return extractResults(response);
    }

    /**
     * 5. 搜索建议（用于搜索框自动补全）
     */
    public List<String> getTopicSuggestions(String prefix) throws IOException {
        SearchResponse<Topic> response = getClient().search(s -> s
                        .index(TOPIC_INDEX)
                        .query(q -> q
                                .prefix(p -> p
                                        .field("title")
                                        .value(prefix)
                                )
                        )
                        .source(sc -> sc.filter(f -> f.includes("title")))
                        .size(5),
                Topic.class
        );

        return response.hits().hits().stream()
                .map(hit -> hit.source() != null ? hit.source().getTitle() : "")
                .filter(title -> !title.isEmpty())
                .collect(Collectors.toList());
    }

    /**
     * 6. 搜索用户发布的话题
     */
    public List<Topic> searchUserTopics(Long userId, String keyword) throws IOException {
        SearchResponse<Topic> response = getClient().search(s -> s
                        .index(TOPIC_INDEX)
                        .query(q -> q
                                .bool(b -> {
                                    if (keyword != null && !keyword.trim().isEmpty()) {
                                        b.must(m -> m
                                                .multiMatch(multi -> multi
                                                        .query(keyword)
                                                        .fields("title", "content")
                                                )
                                        );
                                    }

                                    // 用户ID过滤
                                    b.filter(f -> f
                                            .term(t -> t
                                                    .field("userId")
                                                    .value(userId)
                                            )
                                    );

                                    return b;
                                })
                        )
                        .sort(so -> so.field(f -> f.field("createdAt").order(SortOrder.Desc)))
                        .from(0)
                        .size(50),
                Topic.class
        );

        return extractResults(response);
    }

    /**
     * 提取搜索结果
     */
    private List<Topic> extractResults(SearchResponse<Topic> response) {
        return response.hits().hits().stream()
                .map(Hit::source)
                .filter(topic -> topic != null)
                .collect(Collectors.toList());
    }
}
